/*
Copyright 2008  Four Roads LLC conact@4-roads.com

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either 
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public 
License along with this library.  If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections;
using System.Data;
using System.Data.SqlClient;
using CommunityServer;
using CommunityServer.Configuration;
using CommunityServer.Components;

namespace FourRoads.Links.DataProvider
{
	/// <summary>
	/// Summary description for ResLinkDataProvider.
	/// </summary>
	public abstract class ResLinkDataProvider
	{
		public static readonly string ResLinkDataProviderName = "ResLinkDataProvider";

		#region Instance

		private static ResLinkDataProvider _defaultInstance = null;

		static ResLinkDataProvider()
		{
			CreateDefaultCommonProvider();
		}

		/// <summary>
		/// Returns an instance of the user-specified data provider class.
		/// </summary>
		/// <returns>An instance of the user-specified data provider class.  This class must inherit the
		/// CommonDataProvider interface.</returns>
		public static ResLinkDataProvider Instance() 
		{
			return _defaultInstance;
		}

		public static ResLinkDataProvider Instance (Provider dataProvider) 
		{
			ResLinkDataProvider fdp = CSCache.Get(dataProvider.Name) as ResLinkDataProvider;
			if(fdp == null)
			{
				fdp = DataProviders.Invoke(dataProvider) as ResLinkDataProvider;
				CSCache.Max(dataProvider.Name,fdp);
			}
			return fdp;
		}

		/// <summary>
		/// Creates the Default CommonDataProvider
		/// </summary>
		private static void CreateDefaultCommonProvider()
		{
			// Get the names of the providers
			//
			CSConfiguration config = CSConfiguration.GetConfig();

			// Read the configuration specific information
			// for this provider
			//
			Provider sqlForumsProvider = (Provider) config.Providers[ResLinkDataProviderName];

			// Read the connection string for this provider
			_defaultInstance = DataProviders.CreateInstance(sqlForumsProvider) as ResLinkDataProvider;
		}
    
		#endregion

		public abstract ArrayList GetResLinkPermissions(int sectionID);
		public abstract ResLinkSection GetSectionDetails(int sectionID);
		public abstract void GetSectionDetails(ref ResLinkSection sectionData);
		public abstract int InsertNewSection(ResLinkSection section);
		public abstract void DeleteSection(ResLinkSection section);
		public abstract void UpdateSection(ResLinkSection section);
		public abstract ArrayList GetParentBreadCrumbs(ResLinkSection section);
		public abstract ArrayList GetModerationSummary();
		public abstract void ReportDeadLink(int postId , int userId);
		public abstract ArrayList GetDeadLinkSummary();

		public abstract ArrayList GetLinks(int sectionId , bool viewUnmoderated , bool viewDead);
		public abstract ArrayList GetLinks(int sectionId, bool viewUnmoderated , bool viewDead, LinkViewSort sort);
		public abstract ArrayList GetPagedLinks(int sectionId, bool viewUnmoderated , bool viewDead , int page , int pageCount , LinkViewSort sort , out int moreRecords);
		public abstract ArrayList GetLinkComments(int sectionID,int postId, bool viewUnmoderated);
		public abstract ResLinkLink GetLink(int sectionId , int postId);
		public abstract int InsertNewLink(ResLinkLink link);
		public abstract void UpdateLink(ResLinkLink link);
		public abstract void DeleteLink(ResLinkLink link);
		public abstract void MoveLink(ResLinkLink link , int newSectionID);
		public abstract void UpdateLinkHitCount(int sectionID , int postId);

		public abstract int AddComment(ResLinkComments comment);
		public abstract void UpdateComment(ResLinkComments comment);
		public abstract void DeleteComment(int sectionID ,int postID, int parentID , string reason);

		public abstract Hashtable GetEmailsTrackedBySectionID(int sectionID);

		public abstract SearchResultSet GetSearchResults(SearchQuery query, SearchTerms terms);
		public abstract ArrayList GetAllActiveSections();
		public abstract PostSet SearchReindexPosts (int setsize, int settingsID) ;

		public abstract ArrayList GetRecentlyUpdatedLinks(int top , int sectionID);
		public abstract ArrayList GetPopularLinks(int top , int sectionID);

		public static ResLinkComments CreateLinkCommentInformationFromIDataReader(IDataReader dr)
		{
			ResLinkComments rlc =new ResLinkComments();

			rlc.SectionID = (int) dr["SectionID"];
			rlc.ParentID = (int) dr["ParentID"];
			rlc.PostID = (int) dr["PostID"];
			rlc.Body = Convert.ToString(dr["Body"]).Trim();
			rlc.FormattedBody = Convert.ToString(dr["FormattedBody"]).Trim();
			rlc.CommentRating = (int) dr["Rating"];
			rlc.UserID = (int) dr["UserID"];
			rlc.User =	CommunityServer.Users.GetUser ( rlc.UserID  , true );
			rlc.PostDate  =   (DateTime) dr["PostDate"];
			rlc.IsApproved =   (bool) dr["IsApproved"];
			
			return rlc;
		}

		public static void CreateRootSectionInformationFromIDataReader(IDataReader dr , ref ResLinkSection section)
		{
			section.SectionID = (int) dr["SectionID"];
			section.ParentID = (int) dr["ParentID"];
			section.Name = (string) dr["Name"];
			section.Description = (string) dr["Description"];
			section.IsModerated =  Convert.ToBoolean(dr["IsModerated"]);
			section.ApplicationKey = (string)dr["ApplicationKey"];
			section.IsActive = Convert.ToBoolean(dr["IsActive"]);
			section.ApplicationType = (ApplicationType)ExApplicationType.ResLink;

			SerializerData data = CommonDataProvider.PopulateSerializerDataIDataRecord(dr, (SerializationType)(-1));
		
			section.SetSerializerData(data);
		}

		public static ResLinkLink CreateLinksInformationFromIDataReader(IDataReader dr)
		{
			ResLinkLink post = new ResLinkLink();
			
			try
			{
				post.User =	CommunityServer.Users.GetUser ( (int) dr["UserID"] , true );
			}
			catch(Exception) //Try and get it from a query
			{
			}

			post.SectionID =                (int) dr["SectionID"];
			post.PostID =					(int) dr["PostID"];
			post.Views =                  (int) dr["TotalViews"];
			post.ThreadID =               (int) dr["ThreadID"];
			post.Subject =                Convert.ToString(dr["Subject"]).Trim();
			post.Body =                   Convert.ToString(dr["Body"]).Trim();
			post.Username =				  Convert.ToString(dr["PostAuthor"]).Trim();
			post.PostDate  =             (DateTime) dr["PostDate"];
			post.FormattedBody =         Convert.ToString(dr["FormattedBody"]).Trim();
			post.IsApproved =            (bool) dr["IsApproved"];
			post.LinkUrl =				 Convert.ToString(dr["LinkURL"]).Trim();
			post.ReportedDead =			(bool) dr["ReportedDead"];
			post.ReportingUserID =		(int) dr["ReportingUserID"];
			post.CommentCount	=		(int) dr["CommentCount"];
			post.CommentModerationCount = (int) dr["CommentModerationCount"];
			post.Views = (int) dr["TotalViews"];

			SerializerData data = CommonDataProvider.PopulateSerializerDataIDataRecord(dr, (SerializationType)(-1));
		
			post.SetSerializerData(data);

			post.MostRecentPostAuthor =   (string) dr["MostRecentPostAuthor"];
			post.MostRecentPostAuthorID = (int) dr["MostRecentPostAuthorID"];
			post.RatingSum =  (int) dr["RatingSum"];
			post.TotalRatings = (int) dr["TotalRatings"];

			return post;
		}

		public static void AddSectionPermissions(IDataReader dr , ref ResLinkSection section)
		{
			ResLinkPermission rlbp = new ResLinkPermission();

			CommonDataProvider.PopulatePermissionFromIDataReader(rlbp,dr);

			//Because they are order the most relevant ones are first
			if (section.PermissionSet[rlbp.Name] != null) 
			{

			} 
			else 
			{
				section.PermissionSet.Add(rlbp.Name , rlbp);
			}
		}

		public class ModSummary
		{
			private int _SectionID = 0;
			private string _Name = string.Empty;
			private int _LinkTotal = 0;
			private int _LinkCommentTotal = 0;

			public int LinkTotal
			{
				get {return _LinkTotal;}
				set {_LinkTotal = value;}
			}
			public int LinkCommentTotal
			{
				get {return _LinkCommentTotal;}
				set {_LinkCommentTotal = value;}
			}
			public int SectionID
			{
				get {return _SectionID;}
				set {_SectionID = value;}
			}

			public string Name
			{
				get {return _Name;}
				set {_Name = value;}
			}
		}

		public static void AddModerationSummary(IDataReader dr , ref ArrayList list)
		{
			ModSummary sumary = new ModSummary();

			sumary.Name = (string)dr["Name"];
			sumary.SectionID = (int) dr["SectionID"];
			sumary.LinkTotal = (int) dr["LinkCount"];
			sumary.LinkCommentTotal = (int) dr["CommentCount"];

			list.Add(sumary);
		}

		public class BasicSection
		{
			private string _Name = string.Empty;
			private int _SectionID = 0;

			public string Name
			{
				get{return _Name;} set{_Name = value;}
			}

			public int SectionID 
			{
				get{return _SectionID;} set{_SectionID = value;}
			}

			public int ParentID = 0;
			public string Description = string.Empty;
		}

		public static void AddBasicSection(IDataReader dr , ref ArrayList item)
		{
			BasicSection newSec = new BasicSection();

			newSec.Name = (string)dr["Name"];
			newSec.SectionID = (int) dr["SectionID"];
			newSec.ParentID = (int) dr["ParentID"];
			newSec.Description = (string)dr["Description"];			

			item.Add(newSec);
		}
	}
}
